from random import randint,seed
from BoardCell import BoardCell

class Board:
    def __init__(self,height,width):
        self.width = width
        self.height = height
        self.values = []
        self.setMatrix(BoardCell.Unknown)

#    def copy(self):
#        b = Board(self.height,self.width)
#        for row in xrange(len(self.constraints)):
#            b[row] = self[row][:]
#        return b

    def clearCSPData(self):
        for row in self.values:
            for col in row:
                col.unknowns = []
                col.constraints = []
                col.simulationValue = col

    def randomSquare(self):
        """Randomly returns the (row,col) coordinates of a square"""
        seed()
        c = (randint(0,self.height-1),randint(0,self.width-1))
        while self[c].value != BoardCell.Unknown:
            c = (randint(0,self.height-1),randint(0,self.width-1))
        return c

    def safeSquares(self):
        """Returns a vector of (row,col) tuples where there are safe squares on this board. 
        i.e. nighbours of squares with value zero."""
        ss = []
        for row in xrange(self.height):
            for col in xrange(self.width):
                if self[row][col].value == 0:
                    for t in self.neighbours((row,col),1):
                        if not t in ss and self[t].value == BoardCell.Unknown:
                            ss.append(t)
        return ss

    def neighbours(self,c,span):
        """Returns the neighbouring coordinates (row,col) of the given square.
        The span is the amount of squares to consider from the origin."""
        row = c[0]
        col = c[1]
        neighbours = []
        for r in xrange(row-span,row+span+1):
            for c in xrange(col-span,col+span+1):
                if self.checkBounds(r,c) and (r,c) != (row,col):
                    neighbours.append((r,c))
        return neighbours

    def checkBounds(self,row,col):
        """Checks whether a square is within the bounds of the board"""
        if row < 0 or row >= self.height:
            return False
        if col < 0 or col >= self.width:
            return False
        return True

    def setMatrix(self,value): 
        """Initializes the values of the board matrix to the given value"""
        for i in xrange(self.height):
            self.values.append([])
            for j in xrange(self.width):
                self.values[i].append(BoardCell(value))
                self.values[i][-1].coordinate = (i,j)

    def __getitem__(self,i):
        if isinstance(i,tuple):
            return self[i[0]][i[1]]
        if i < 0 or i >= self.height:
            raise IndexError
        return self.values[i]

    def __setitem__(self,i,obj):
        self.values[i] = obj
        col = 0
        for cell in obj:
            cell.coordinate = (i,col)
            col+=1

    def printRep(self):
        for i in xrange(self.height):
            for cell in self.values[self.height -i -1]:
                print str(cell.value) + " ",
            print ""

